#include "ESP.h"

ESP g_pESP;

void ESP::Init()
{
	static bool bInit = false;
	if(!bInit)
	{
		g_pInterfaces.g_pRadar = *(RadarClass**) ((**(DWORD**) (FindPattern::Find((DWORD)GetModuleHandle(L"client.dll"), 0x89B000 - 0x100, (BYTE*) RadarFindPatternA, RadarFindPatternB) + RadarPatternOffset)) + 0xC);

		g_pWeaponFont = Font::BuildFont("cs", 28, 350, FF_OUTLINE|FF_DROPSHADOW);

		Active = true;
		TeamCTColor = 0xFF00FFFF;
		TeamTColor = 0xFFFF0000;
		TeamCTColorB = 0xFF00FF00;
		TeamTColorB = 0xFFFFFF00;
		DrawHP = true;
		DrawName = true;
		DrawHead = true;
		DrawFar = true;
		DrawWeapon = true;
		DrawSkeleton = true;
		DrawEntities = true;
		bInit = true;
	}
}

void ESP::Enable()
{
	Active = true;
}

void ESP::Disable()
{
	Active = false;
}

void ESP::Set( bool Active )
{
	this->Active = Active;
}

void ESP::SetDrawHp( bool Active )
{
	DrawHP = Active;
}

void ESP::SetDrawName( bool Active )
{
	DrawName = Active;
}

void ESP::SetDrawHead( bool Active )
{
	DrawHead = true;
}

void ESP::SetCTColor( DWORD Color )
{
	TeamCTColor = Color;
}

void ESP::SetTColor( DWORD Color )
{
	TeamTColor = Color;
}

void ESP::SetFarEsp( bool Active )
{
	DrawFar = Active;
}

void ESP::DrawLine( SD_Tools::Vector2& a, SD_Tools::Vector2& b, DWORD Color )
{
	GRender.LineRGBA((int) a.x, (int) a.y, (int) b.x, (int) b.y, (Color>>16)&0xFF, (Color>>8)&0xFF, (Color>>0)&0xFF, (Color>>24)&0xFF);
}

void ESP::DrawFullSkeleton( Entity* Ent, DWORD Color )
{
	SD_Tools::Vector2 ScreenSize;
	int tempa;
	int tempb;
	g_pInterfaces.g_pEngine->GetScreenSize(&tempa, &tempb);
	ScreenSize.x = (float) tempa;
	ScreenSize.y = (float) tempb;

	SD_Tools::Vector2 LFoot;
	SD_Tools::Vector2 RFoot;
	SD_Tools::Vector2 LKnee;
	SD_Tools::Vector2 RKnee;
	SD_Tools::Vector2 LHip;
	SD_Tools::Vector2 RHip;
	SD_Tools::Vector2 Hip;
	SD_Tools::Vector2 Spine;
	SD_Tools::Vector2 Neck;
	SD_Tools::Vector2 Head;
	SD_Tools::Vector2 LShoulder;
	SD_Tools::Vector2 RShoulder;
	SD_Tools::Vector2 LElbow;
	SD_Tools::Vector2 RElbow;
	SD_Tools::Vector2 LHand;
	SD_Tools::Vector2 RHand;

	SD_Tools::Vector TempVec;

	Ent->GetBone(BONE_L_FOOT, &TempVec);
	if (!GameUtilities::WorldToScreen(*g_pInterfaces.g_pEngine->WorldToScreenMatrix(), ScreenSize, TempVec, &LFoot))
		return;

	Ent->GetBone(BONE_R_FOOT, &TempVec);
	if (!GameUtilities::WorldToScreen(*g_pInterfaces.g_pEngine->WorldToScreenMatrix(), ScreenSize, TempVec, &RFoot))
		return;

	Ent->GetBone(BONE_L_CALF, &TempVec);
	if (!GameUtilities::WorldToScreen(*g_pInterfaces.g_pEngine->WorldToScreenMatrix(), ScreenSize, TempVec, &LKnee))
		return;

	Ent->GetBone(BONE_R_CALF, &TempVec);
	if (!GameUtilities::WorldToScreen(*g_pInterfaces.g_pEngine->WorldToScreenMatrix(), ScreenSize, TempVec, &RKnee))
		return;

	Ent->GetBone(BONE_L_THIGH, &TempVec);
	if (!GameUtilities::WorldToScreen(*g_pInterfaces.g_pEngine->WorldToScreenMatrix(), ScreenSize, TempVec, &LHip))
		return;

	Ent->GetBone(BONE_R_THIGH, &TempVec);
	if (!GameUtilities::WorldToScreen(*g_pInterfaces.g_pEngine->WorldToScreenMatrix(), ScreenSize, TempVec, &RHip))
		return;

	Ent->GetBone(BONE_PELVIS, &TempVec);
	if (!GameUtilities::WorldToScreen(*g_pInterfaces.g_pEngine->WorldToScreenMatrix(), ScreenSize, TempVec, &Hip))
		return;

	Ent->GetBone(BONE_SPINE1, &TempVec);
	if (!GameUtilities::WorldToScreen(*g_pInterfaces.g_pEngine->WorldToScreenMatrix(), ScreenSize, TempVec, &Spine))
		return;

	Ent->GetBone(BONE_NECK, &TempVec);
	if (!GameUtilities::WorldToScreen(*g_pInterfaces.g_pEngine->WorldToScreenMatrix(), ScreenSize, TempVec, &Neck))
		return;

	Ent->GetBone(BONE_HEAD, &TempVec);
	TempVec.z += 3.0f;
	if (!GameUtilities::WorldToScreen(*g_pInterfaces.g_pEngine->WorldToScreenMatrix(), ScreenSize, TempVec, &Head))
		return;

	Ent->GetBone(BONE_L_CLAVICLE, &TempVec);
	if (!GameUtilities::WorldToScreen(*g_pInterfaces.g_pEngine->WorldToScreenMatrix(), ScreenSize, TempVec, &LShoulder))
		return;

	Ent->GetBone(BONE_R_CLAVICLE, &TempVec);
	if (!GameUtilities::WorldToScreen(*g_pInterfaces.g_pEngine->WorldToScreenMatrix(), ScreenSize, TempVec, &RShoulder))
		return;

	Ent->GetBone(BONE_L_FOREARM, &TempVec);
	if (!GameUtilities::WorldToScreen(*g_pInterfaces.g_pEngine->WorldToScreenMatrix(), ScreenSize, TempVec, &LElbow))
		return;

	Ent->GetBone(BONE_R_FOREARM, &TempVec);
	if (!GameUtilities::WorldToScreen(*g_pInterfaces.g_pEngine->WorldToScreenMatrix(), ScreenSize, TempVec, &RElbow))
		return;

	Ent->GetBone(BONE_L_HAND, &TempVec);
	if (!GameUtilities::WorldToScreen(*g_pInterfaces.g_pEngine->WorldToScreenMatrix(), ScreenSize, TempVec, &LHand))
		return;

	Ent->GetBone(BONE_R_HAND, &TempVec);
	if (!GameUtilities::WorldToScreen(*g_pInterfaces.g_pEngine->WorldToScreenMatrix(), ScreenSize, TempVec, &RHand))
		return;

	DrawLine(LFoot, LKnee, Color);
	DrawLine(LKnee, LHip, Color);
	DrawLine(LHip, Hip, Color);
	DrawLine(RFoot, RKnee, Color);
	DrawLine(RKnee, RHip, Color);
	DrawLine(RHip, Hip, Color);
	DrawLine(Hip, Spine, Color);
	DrawLine(Spine, Neck, Color);
	DrawLine(Neck, Head, Color);
	DrawLine(Neck, LShoulder, Color);
	DrawLine(LShoulder, LElbow, Color);
	DrawLine(LElbow, LHand, Color);
	DrawLine(Neck, RShoulder, Color);
	DrawLine(RShoulder, RElbow, Color);
	DrawLine(RElbow, RHand, Color);

	//////////////////////////////////////////////////////////////////////////

	/*SD_Tools::Vector RealHead;
	SD_Tools::Vector HeadBone;
	SD_Tools::Vector NeckBone;
	SD_Tools::Vector2 PreRealHeadScreen;
	SD_Tools::Vector2 RealHeadScreen;
	Ent->GetBone(BONE_HEAD, &HeadBone);
	Ent->GetBone(BONE_NECK, &NeckBone);
	RealHead = SD_Tools::MathHelper::SubVector(HeadBone, NeckBone);
	RealHead.Multiply(1.6f);
	RealHead.Add(NeckBone);
	
	if (!GameUtilities::WorldToScreen(*g_pInterfaces.g_pEngine->WorldToScreenMatrix(), ScreenSize, RealHead, &PreRealHeadScreen))
		return;

	RealHead.z += 2.0f;

	if (!GameUtilities::WorldToScreen(*g_pInterfaces.g_pEngine->WorldToScreenMatrix(), ScreenSize, RealHead, &RealHeadScreen))
		return;

	DrawLine(Neck, PreRealHeadScreen, 0xFFFFFFFF);
	DrawLine(PreRealHeadScreen, RealHeadScreen, 0xFFFFFFFF);*/

	//////////////////////////////////////////////////////////////////////////
	//////////////////////////////////////////////////////////////////////////

	/*Entity* LocalEnt = g_pInterfaces.g_pEntList->GetClientEntity(g_pInterfaces.g_pEngine->GetLocalPlayer());

	if (!LocalEnt)
		return;

	SD_Tools::Vector Origin = LocalEnt->GetEyePosition();
	SD_Tools::Vector NormalVec = SD_Tools::MathHelper::SubVector(Origin, RealHead);
	float TempFloat = 1/NormalVec.Magnitude();
	NormalVec.Multiply(TempFloat);

	float PlaneD = NormalVec.x * RealHead.x + NormalVec.y * RealHead.y + NormalVec.z * RealHead.z;

	SD_Tools::Vector RangeVec;
	SD_Tools::Vector TempVec1;
	SD_Tools::Vector TempVec2;
	SD_Tools::Vector TempVec3;

	TempVec1.Clear();
	TempVec2.Clear();
	TempVec3.Clear();

	if (NormalVec.y != 0.0f)
	{
		TempVec1.x = 0.0f;
		TempVec1.y = PlaneD/NormalVec.y;
		TempVec1.z = 0.0f;
	}
	if (NormalVec.x != 0.0f)
	{
		TempVec2.x = PlaneD/NormalVec.x;
		TempVec2.y = 0.0f;
		TempVec2.z = 0.0f;
	}
	if (NormalVec.z != 0.0f)
	{
		TempVec3.x = 0.0f;
		TempVec3.y = 0.0f;
		TempVec3.z = PlaneD/NormalVec.z;
	}

	RangeVec = (TempVec1.MagnitudeSqr() > TempVec2.MagnitudeSqr()) ? TempVec1 : TempVec2;
	RangeVec = (RangeVec.MagnitudeSqr() > TempVec3.MagnitudeSqr()) ? RangeVec : TempVec3;

	TempFloat = 1/RangeVec.Magnitude();
	RangeVec.Multiply(TempFloat);
	RangeVec.Multiply(5.0f); // Size

	SD_Tools::Vector RangeVecA = RealHead;
	RangeVecA.Add(RangeVec);
	 
	SD_Tools::Vector2 RangeVecAScreen;

	if (!GameUtilities::WorldToScreen(*g_pInterfaces.g_pEngine->WorldToScreenMatrix(), ScreenSize, RangeVecA, &RangeVecAScreen))
		return;

	DrawLine(RealHeadScreen, RangeVecAScreen, 0xFFFFFF00);*/

	//////////////////////////////////////////////////////////////////////////
}

void ESP::Draw()
{
	if (Active)
	{
		int MaxEntities = g_pInterfaces.g_pEntList->GetHighestEntityIndex();
		int LocalPlayerIndex = g_pInterfaces.g_pEngine->GetLocalPlayer();
		Entity* LocalEntity = g_pInterfaces.g_pEntList->GetClientEntity(LocalPlayerIndex);

		bool DrawnEntity[32] = { false };
		SD_Tools::Vector OwnHead = LocalEntity->GetEyePosition();

		SD_Tools::Vector2 ScreenSize;
		int tempa;
		int tempb;
		g_pInterfaces.g_pEngine->GetScreenSize(&tempa, &tempb);
		ScreenSize.x = (float) tempa;
		ScreenSize.y = (float) tempb;
		player_info_t pinfo;
		SD_Tools::Vector2 SBot;
		SD_Tools::Vector2 STop;
		SD_Tools::Vector2 SHead;
		bool DoDrawHead;
		bool DoDrawWeapon;
		char* TargetName;
		int TargetHp;
		DWORD DrawColor;
		char WeaponChar;


		for (int i = 0; i < MaxEntities; i++)
		{
			if(i == LocalPlayerIndex)
			{
				continue;
			}

			Entity* baseEnt = g_pInterfaces.g_pEntList->GetClientEntity(i);

			if(!baseEnt)
			{
				continue;
			}

			if(DrawEntities && !(*baseEnt->dormant()))
			{
				LPCSTR lpClass = baseEnt->GetClientClass()->m_pNetworkName;

				if(strstr(lpClass, "CWeapon") || !lstrcmpA(lpClass, "CC4") || !lstrcmpA(lpClass, "CAK47") || !lstrcmpA(lpClass, "CDEagle"))
				{
					CBaseCombatWeapon* baseWeapon = (CBaseCombatWeapon*)baseEnt;

					if(!baseWeapon)
						continue;

					if(baseWeapon->GetOwner() != -1) // Weapon is not owned by a player
						continue;

					SD_Tools::Vector  Bone;
					SD_Tools::Vector2 Screen;
					baseEnt->GetBone(0, &Bone);
					if(GameUtilities::WorldToScreen(*g_pInterfaces.g_pEngine->WorldToScreenMatrix(), ScreenSize, Bone, &Screen))
					{
						g_pWeaponFont->PrintString((int)Screen.x, (int)Screen.y, 255, 255, 255, 255, FA_CenterH|FA_CenterW, "%c", GameUtilities::GetWeaponChar(baseWeapon->GetWeaponId())); 
					}
				}
			}

			// Valid:
			DoDrawHead = true;
			DoDrawWeapon = false;
			TargetName = "INVALID";
			TargetHp = 1337;
			DrawColor = 0xFF000000;

			if (*baseEnt->dormant() || !g_pInterfaces.g_pEngine->GetPlayerInfo(i, &pinfo) || *baseEnt->lifeState() != 0) // FARESP
			{
				if (DrawFar && i > 1 && i <= 32)
				{
					SD_Tools::Vector bot;
					SD_Tools::Vector top;
					RadarPlayer* Player;

					Player = &g_pInterfaces.g_pRadar->Players[i-1];

					if (!(Player->Team == TeamCT || Player->Team == TeamT) || Player->Hp <= 0 || Player->Position.x == 0 || Player->Position.y == 0)
					{
						continue;
					}

					bot = Player->Position;
					top = bot;
					top.z += 70.0f;

					if(!GameUtilities::WorldToScreen(*g_pInterfaces.g_pEngine->WorldToScreenMatrix(), ScreenSize, bot, &SBot) || !GameUtilities::WorldToScreen(*g_pInterfaces.g_pEngine->WorldToScreenMatrix(), ScreenSize, top, &STop))
					{
						continue;
					}

					TargetName = Player->Name;
					TargetHp = Player->Hp;

					if (Player->Team == TeamCT)
					{
						DrawColor = TeamCTColorB;
					}
					else
					{
						DrawColor = TeamTColorB;
					}

					DoDrawHead = false;
				}
				else
				{
					continue;
				}
			}
			else // NORMALESP
			{
				SD_Tools::Vector bot;
				SD_Tools::Vector top;
				SD_Tools::Vector head;

				if (!baseEnt->GetBone(BONE_L_FOOT, &bot))
				{
					bot = *baseEnt->vecOrigin();
				}

				if (!baseEnt->GetBone(BONE_HEAD, &top))
				{
					top = bot;
					top.z += 62.0f;
				}
				top.z += 8.0f;

				head = top;

				if(!GameUtilities::WorldToScreen(*g_pInterfaces.g_pEngine->WorldToScreenMatrix(), ScreenSize, bot, &SBot) || !GameUtilities::WorldToScreen(*g_pInterfaces.g_pEngine->WorldToScreenMatrix(), ScreenSize, top, &STop))
				{
					continue;
				}

				if (!GameUtilities::WorldToScreen(*g_pInterfaces.g_pEngine->WorldToScreenMatrix(), ScreenSize, head, &SHead))
				{
					DoDrawHead = false;
				}

				TargetName = pinfo.name;
				TargetHp = *baseEnt->iHealth();

				CBaseCombatWeapon* TempWeapon = GameUtilities::GetBaseCombatWeapon(baseEnt);
				if (TempWeapon)
				{
					WeaponChar = GameUtilities::GetWeaponChar(TempWeapon->GetWeaponId());
					DoDrawWeapon = true;
				}

				if (GameUtilities::IsVisible(OwnHead, head, LocalEntity, baseEnt))
				{
					if (*baseEnt->iTeamNum() == TeamCT)
					{
						DrawColor = TeamCTColor;
					}
					else
					{
						DrawColor = TeamTColor;
					}
				}
				else
				{
					if (*baseEnt->iTeamNum() == TeamCT)
					{
						DrawColor = TeamCTColorB;
					}
					else
					{
						DrawColor = TeamTColorB;
					}
				}
				if (DrawSkeleton)
				{
					DrawFullSkeleton(baseEnt, DrawColor);
				}
			}

			float h = SBot.y - STop.y;
			float w = h*0.618033f;

			GRender.CornerBox((int)(STop.x - w/2), (int)STop.y, 10, (int)w, (int)h, (DrawColor>>16)&0xFF, (DrawColor>>8)&0xFF, (DrawColor>>0)&0xFF, (DrawColor>>24)&0xFF);
			if (DrawHead && DoDrawHead)
			{
				GRender.FillRGBA((int)SHead.x-2, (int)SHead.y, 4, 4, (DrawColor>>16)&0xFF, (DrawColor>>8)&0xFF, (DrawColor>>0)&0xFF, (DrawColor>>24)&0xFF);
			}
			if (DrawName)
			{
				g_pFont->PrintString((int) (STop.x - w/2), (int) (SBot.y + 5.0f), 255, 255, 255, 255, FA_Left, "(%s)", TargetName);
			}
			if (DrawHP)
			{
				g_pFont->PrintString((int) (STop.x + w/2 + 14), (int) STop.y, (DrawColor>>16)&0xFF, (DrawColor>>8)&0xFF, (DrawColor>>0)&0xFF, (DrawColor>>24)&0xFF, FA_Left, "HP: %d", TargetHp);
			}
			if (DrawWeapon && DoDrawWeapon)
			{
				g_pWeaponFont->PrintString((int) (STop.x + w/2 + 14), (int) SBot.y - 30, 255, 255, 255, 255, FA_Left, "%c", WeaponChar);
			}
		}
	}
}